package com.cqfae.deploycentral.app.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atlassian.jira.rest.client.JiraRestClient;
import com.atlassian.jira.rest.client.JiraRestClientFactory;
import com.atlassian.jira.rest.client.ProjectRestClient;
import com.atlassian.jira.rest.client.domain.*;
import com.atlassian.jira.rest.client.domain.input.VersionInput;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.cqfae.deploycentral.app.config.JiraIssues;
import com.cqfae.deploycentral.app.services.ConstantsCodeService;
import com.cqfae.deploycentral.app.web.response.JiraInfo;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.cqfae.deploycentral.app.base.BaseConstantCode.*;

@Component
public class JiraAPIUtil{

    private static Logger logger = LoggerFactory.getLogger(JiraAPIUtil.class);

    JiraRestClient client;

    @Value("${jira.url}")
    private String jiraUrl;

    @Value("${jira.userName}")
    private String jiraUserName;

    @Value("${jira.password}")
    private String jiraPassword;

    @Autowired
    private ConstantsCodeService constantsCodeService;

    /**
     * 查询JIRA所有的project信息
     * @return
     */
    public List<JiraInfo> getJIRAProjectInfo(){
        JiraRestClient restClient = getJiraRestClient();
        List<JiraInfo> jiraInfoList = new ArrayList<>();
        Iterable<BasicProject>  basicProjects = restClient.getProjectClient().getAllProjects().claim();
        for(BasicProject basicProject:basicProjects){
            JiraInfo jiraInfo = new JiraInfo();
            jiraInfo.setProjectKey(basicProject.getKey());
            jiraInfo.setProjectName(basicProject.getName());
            jiraInfoList.add(jiraInfo);
        }
        return jiraInfoList;
    }

    /**
     * 修改jira版本的状态值
     * @param versionInfo
     * @return
     */
    public int changeVersionStatus(JiraInfo versionInfo){
        JiraRestClient restClient = getJiraRestClient();
        logger.info( "======================= Start:changeVersionStatus==========================");
        VersionInput versionInput = new VersionInput(
                versionInfo.getProjectKey(),
                versionInfo.getVersionName(),
                versionInfo.getVersionDescription(),
                versionInfo.getReleaseDate(),
                false,
                true);
        Version version =  restClient.getVersionRestClient().updateVersion(versionInfo.getSelf(),versionInput).claim();
        if(version.isReleased()){
            logger.info( "======================= End:changeVersionStatus is Success ==========================");
            return SCHEDULED_EXEC_SUCCESS;
        }else{
            logger.info( "======================= End:changeVersionStatus isn't Response Now,threeHand is Begin==========================");
            return threeHand(versionInfo,versionInput);
        }
    }
    /**
     * 因为是异步处理，所以状态是延迟变更的，重新执行修改
     * @param versionInfo
     * @param versionInput
     * @return
     */
    public int threeHand(JiraInfo versionInfo,VersionInput versionInput){
        JiraRestClient restClient = getJiraRestClient();
        int executeResult = SCHEDULED_EXEC_NOTHING;
        try {
            for (int i = 0; i < 2 ; i++) {
                Thread.sleep(4000);
                Version version = restClient.getVersionRestClient().updateVersion(versionInfo.getSelf(),versionInput).claim();
                if(version.isReleased()){
                    executeResult = SCHEDULED_EXEC_SUCCESS;
                    break;
                }else{
                    executeResult =  SCHEDULED_EXEC_FAIL;
                }
            }
        } catch (InterruptedException e) {
            logger.info( "====================threeHand InterruptedException e ==========================",e );
            Thread.currentThread().interrupt();
        }
        if(executeResult==SCHEDULED_EXEC_NOTHING){
            logger.info( "====================End: threeHand is Done,But change JIRA's STATUS is fail,suggest check Version Status ==========================",versionInfo.getVersionId());
        }
        return executeResult;
    }

    /**
     * 各个项目组待发布的版本信息+改版本下的Issues信息
     * @return List<JiraInfo>
     */
    public List<JiraInfo> geDetailInfoReVersion(){
        logger.info( "======================= Start:geDetailInfoReVersion:==========================");
        //CopyOnWriteArrayList实现集合在add操作时的安全锁（线程安全）JDK1.7.0_40版本支持
        List<JiraInfo> exceptList = new CopyOnWriteArrayList<>();
        List<JiraInfo> readyForVersionList = getReadyForReleasedVersion();
        for(JiraInfo versionInfo : readyForVersionList){
            //测试报告所期待的完整信息
            JiraInfo jiraInfo = new JiraInfo();
            //调用第searchJal去查询版本下关联的issues信息
            String jql = "fixVersion = " + versionInfo.getVersionId();
            List<JiraIssues> jiraIssuesList = getIssueList(jql,null);
            jiraInfo.setIssuesList(jiraIssuesList);
            //版本基本信息
            jiraInfo.setVersionId(versionInfo.getVersionId());
            jiraInfo.setVersionName(versionInfo.getVersionName());
            jiraInfo.setVersionDescription(versionInfo.getVersionDescription());
            exceptList.add(jiraInfo);
        }
        if(exceptList.isEmpty()){
            logger.info( "==================== End:geDetailInfoReVersion is done,but queryInfo is Nothing==========================");
        }else{
            logger.info( "==================== End:geDetailInfoReVersion is done ==========================");
        }
        return exceptList;
    }

    /**
     * 单个版本信息+改版本下的Issues信息(该接口不受版本状态的限制)
     * @param  versionId
     * @return JiraInfo
     */
    public JiraInfo getOneInfoReVersion(Long versionId){
        logger.info( "======================= Start:getOneInfoReVersion,The VersionId:"+versionId+"==========================");
        //调用第searchJal去查询版本下关联的issues（Story）信息
        String jql = "fixVersion = " + versionId;
        List<JiraIssues> jiraIssuesList = getIssueList(jql,null);
        //取story的集合中取组别和版本的基础信息（stroy不会对应多个版本的情况，已和JIRA设计确认）
        String projectKey = "";
        String projectName = "";
        String versionName = "";
        Long verId = null;
        for(JiraIssues jiraIssues:jiraIssuesList){
            projectKey = jiraIssues.getProjectKey();
            projectName = jiraIssues.getProjectName();
            verId = jiraIssues.getVersionId();
            versionName = jiraIssues.getVersionName();
        }
        //调用第searchJal去查询版本下关联的issues（Story-Bug）信息
        List<JiraIssues> buglist = new CopyOnWriteArrayList<>(  );
        String associatedWithSB = constantsCodeService.getNameByCode("jiraJQL.associatedWithSB");
        for(JiraIssues jiraIssues:jiraIssuesList){
            String jql1 = associatedWithSB + " = " + jiraIssues.getIssuesKey();
            buglist.addAll( getIssueList(jql1,jiraIssues.getIssuesKey()) );
        }
        //将story下的bug的集合信息和版本下的story集合进行融合
        jiraIssuesList.addAll( buglist );
        //测试报告所期待的完整信息
        JiraInfo jiraInfo = new JiraInfo();
        jiraInfo.setProjectKey( projectKey );
        jiraInfo.setProjectName( projectName );
        jiraInfo.setVersionId( verId );
        jiraInfo.setVersionName( versionName );
        jiraInfo.setIssuesList(jiraIssuesList);
        if(NullUtil.isEmpty(jiraInfo)){
            logger.info( "==================== End:getOneInfoReVersion is done,but queryInfo is Nothing==========================");
        }else{
            logger.info( "==================== ResultInfo:getOneInfoReVersion is start ==========================");
            logger.info(GsonUtils.getInstance().toJson(jiraInfo));
            logger.info( "==================== ResultInfo:getOneInfoReVersion is done  ==========================");
        }
        return jiraInfo;
    }

    /**
     * 查询JQL条件查询issues的集合
     * @param jql
     * @param stroyKey
     * @return List<JiraIssues>
     */
    public List<JiraIssues> getIssueList(String jql,String stroyKey){
        JiraRestClient restClient = getJiraRestClient();
        Iterable<BasicIssue> issueIterable = restClient.getSearchClient().searchJql(jql).claim().getIssues();
        List<JiraIssues> jiraIssuesList = new CopyOnWriteArrayList<>();
        for(BasicIssue basicIssue:issueIterable) {
            //issues信息大范围是满足类型为story和Bug的
            Issue issue = restClient.getIssueClient().getIssue(basicIssue.getKey()).claim();
            String checkedIssueType = constantsCodeService.getNameByCode("jiraJQL.checkedIssueType");
            if(checkedIssueType.contains( issue.getIssueType().getName() )){
                JiraIssues jiraIssues = new JiraIssues();
                jiraIssues.setIssuesName(issue.getSummary());
                jiraIssues.setDescription(issue.getDescription());
                if(NullUtil.isNotEmpty(issue.getAssignee())){
                    jiraIssues.setAssignee(issue.getAssignee().getName());
                }
                if(NullUtil.isNotEmpty(issue.getReporter())){
                    jiraIssues.setReporter(issue.getReporter().getName());
                }

                //给的是状态的中文值
                jiraIssues.setIssuesStatu(issue.getStatus().getName());
                jiraIssues.setTypeName(issue.getIssueType().getName() );
                jiraIssues.setSelf(issue.getStatus().getSelf());
                jiraIssues.setIssuesKey(basicIssue.getKey());
                jiraIssues.setPriority( issue.getPriority().getId() +"" );
                //自定义的字段值的取值（“发现阶段”）
                Iterable<Field> fields = issue.getFields();
                String discoveryStage = detailDefine(fields);
                jiraIssues.setDiscovryStage( discoveryStage );
                jiraIssues.setStoryKey(stroyKey);
                //创建时间
                DateTime createTime = issue.getCreationDate();
                Date createDate = createTime.toDate();
                jiraIssues.setCreateDate(ConvertUtil.convertDJTS(createDate));
                //项目相关信息：getProjectKey，getProjectName，getVersionId，getVersionName
                jiraIssues.setProjectKey( issue.getProject().getKey() );
                jiraIssues.setProjectName( issue.getProject().getName() );
                Iterable<Version> versionIterable = issue.getFixVersions();
                for(Version version:versionIterable){
                    jiraIssues.setVersionId( version.getId() );
                    jiraIssues.setVersionName( version.getName() );
                }
                jiraIssuesList.add(jiraIssues);
            }
        }
        return jiraIssuesList;
    }
    /**
     * 处理自定义字段:发现阶段的值
     * @param fields
     * @return String
     */
    public String detailDefine(Iterable<Field> fields){
        String discoveryStage = "";
        String discoveryStageName = constantsCodeService.getNameByCode("jiraJQL.discoveryStageName");
        for (Field field:fields) {
            if(discoveryStageName.equals( field.getName())){
                JSONObject jsonObject = JSON.parseObject(field.getValue()+"");
                if(NullUtil.isNotEmpty( jsonObject )){
                    discoveryStage = jsonObject.getString( "value" );
                }
                break;
            }
        }
        return discoveryStage;
    }

    /**
     * 各个项目组待发布的版本信息
     * @return List<JiraInfo>
     */
    public List<JiraInfo> getReadyForReleasedVersion(){
        JiraRestClient restClient = getJiraRestClient();
        logger.info( "==================== Start:getReadyForReleasedVersion ==========================");
        //CopyOnWriteArrayList实现集合在add操作时的安全锁（线程安全）JDK1.7.0_40版本支持
        List<JiraInfo> readyForReleasedVersionList = new CopyOnWriteArrayList<>();
        //projectRestClient 所有项目组的相关信息
        ProjectRestClient projectRestClient = restClient.getProjectClient();
        //获取现有所有的项目组基础信息
        Iterable<BasicProject> basicProjectIterable = projectRestClient.getAllProjects().claim();
        for(BasicProject basicProject : basicProjectIterable){
            String projectKey   = basicProject.getKey();
            String projectName  = basicProject.getName();
            //从获取到的项目信息提出Key值查询该项目的版本信息
            Iterable<Version> versionIterable   = projectRestClient.getProject(projectKey).claim().getVersions();
            //从版本信息中筛选出未发布的版本
            for(Version projectVersion:versionIterable){
                if(!projectVersion.isArchived() && !projectVersion.isReleased()){
                    JiraInfo jiraInfo = new JiraInfo();
                    jiraInfo.setVersionId(projectVersion.getId());
                    jiraInfo.setCode( projectVersion.getId() );
                    jiraInfo.setVersionName(projectVersion.getName());
                    jiraInfo.setName("【"+projectName+"】"+projectVersion.getName());
                    jiraInfo.setVersionDescription(projectVersion.getDescription());
                    jiraInfo.setReleaseDate(projectVersion.getReleaseDate());
                    jiraInfo.setSelf(projectVersion.getSelf());
                    jiraInfo.setProjectKey(projectKey);
                    jiraInfo.setProjectName(projectName);
                    readyForReleasedVersionList.add(jiraInfo);
                }
            }
        }
        if(readyForReleasedVersionList.isEmpty()){
            logger.info( "==================== End:readyForReleasedVersionList is done,but queryInfo is Nothing==========================");
        }else{
            logger.info( "==================== ResultInfo:getReadyForReleasedVersion is start ==========================");
            logger.info( GsonUtils.getInstance().toJson(readyForReleasedVersionList));
            logger.info( "==================== ResultInfo:getReadyForReleasedVersion is done ==========================");
        }
        return readyForReleasedVersionList;
    }

    /**
     * 获得jira的客户端
     * @return JiraRestClient
     */
    public JiraRestClient getJiraRestClient() {
        JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
        if (client == null) {
            try {
                URI jiraServerUri = new URI(jiraUrl);
                client = factory.createWithBasicHttpAuthentication(jiraServerUri, jiraUserName, jiraPassword);
            } catch (URISyntaxException e) {
                logger.info("=====================Error:getJiraRestClient URISyntaxException ==========================",e);
            }
        }
        return client;
    }
}
